package com.jing.yuntuku.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.jing.yuntuku.constant.FileConstant;
import com.jing.yuntuku.exception.BusinessException;
import com.jing.yuntuku.exception.ErrorCode;
import com.jing.yuntuku.model.bean.Picture;
import com.jing.yuntuku.model.bean.User;
import com.jing.yuntuku.model.dto.picture.PictureQueryDto;
import com.jing.yuntuku.model.dto.picture.PictureReviewDto;
import com.jing.yuntuku.model.dto.picture.PictureUploadDto;
import com.jing.yuntuku.model.dto.picture.PictureVO;
import com.jing.yuntuku.model.dto.file.UploadPictureResult;
import com.jing.yuntuku.model.enums.PictureReviewStatusEnum;
import com.jing.yuntuku.model.vo.UserVO;
import com.jing.yuntuku.service.PictureService;
import com.jing.yuntuku.mapper.PictureMapper;

import com.jing.yuntuku.service.UserService;
import com.jing.yuntuku.utils.ThrowUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 18151
 * @description 针对表【picture(图片)】的数据库操作Service实现
 * @createDate 2025-09-12 14:28:59
 */
@Service
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
        implements PictureService {

    @Resource
    private FileManager fileManager;

    @Resource
    private UserService userService;

    /**
     * 上传或者更新图片
     *
     * @param multipartFile
     * @param pictureUploadDto
     * @param loginUser
     * @return
     */
    @Override
    public PictureVO uploadPicture(Object multipartFile, PictureUploadDto pictureUploadDto, User loginUser) {
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);

        Long pictureId = null;
        if (pictureUploadDto != null) {
            pictureId = pictureUploadDto.getId();
        }
        UploadPictureResult uploadPictureResult;


        if (pictureId != null) {
            Picture oldPicture = this.getById(pictureId);
            ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND_ERROR, "图片不存在");

            if (!oldPicture.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        }
        if (multipartFile instanceof MultipartFile) {
            MultipartFile file = (MultipartFile) multipartFile;
            uploadPictureResult = fileManager.uploadFileAndGetInfo(file, (FileConstant.File + loginUser.getId()));
            return upoad(uploadPictureResult,pictureId,loginUser);
        }
        if(multipartFile instanceof String) {
            String url = (String) multipartFile;
            uploadPictureResult = fileManager.uploadPictureByUrl(url, (FileConstant.File + loginUser.getId()));
            return upoad(uploadPictureResult,pictureId,loginUser);
        }


        throw new BusinessException(ErrorCode.SYSTEM_ERROR,"传入的文件有问题，请使用url上传或者图片文件上传");
    }

    private PictureVO upoad(UploadPictureResult uploadPictureResult,Long pictureId,User loginUser) {
        Picture picture = new Picture();
        BeanUtils.copyProperties(uploadPictureResult, picture);
        picture.setName(uploadPictureResult.getPicName());
        if (pictureId != null) {

            picture.setId(pictureId);
            picture.setEditTime(new Date());
        }
        picture.setUserId(loginUser.getId());
        fillReviewParams(picture,loginUser);
        boolean result = this.saveOrUpdate(picture);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败");
        return PictureVO.objToVo(picture);
    }
    /**
     * 分页查询
     *
     * @param pictureQueryDto
     * @return
     */
    @Override
    public QueryWrapper<Picture> getQueryWrapper(PictureQueryDto pictureQueryDto) {
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
        if (pictureQueryDto == null) {
            return pictureQueryWrapper;
        }
        Long id = pictureQueryDto.getId();
        String name = pictureQueryDto.getName();
        String introduction = pictureQueryDto.getIntroduction();
        String category = pictureQueryDto.getCategory();
        List<String> tags = pictureQueryDto.getTags();
        Long picSize = pictureQueryDto.getPicSize();
        Integer picWidth = pictureQueryDto.getPicWidth();
        Integer picHeight = pictureQueryDto.getPicHeight();
        Double picScale = pictureQueryDto.getPicScale();
        String picFormat = pictureQueryDto.getPicFormat();
        String searchText = pictureQueryDto.getSearchText();
        Long userId = pictureQueryDto.getUserId();
        Integer reviewStatus = pictureQueryDto.getReviewStatus();
        String reviewMessage = pictureQueryDto.getReviewMessage();
        Long reviewerId = pictureQueryDto.getReviewerId();


//        Integer current = pictureQueryDto.getCurrent();
//        Integer pageSize = pictureQueryDto.getPageSize();
        String sortField = pictureQueryDto.getSortField();
        String sortOrder = pictureQueryDto.getSortOrder();

        if (StrUtil.isNotBlank(searchText)) {
            pictureQueryWrapper.and(qw -> qw.like("name", searchText)
                    .or()
                    .like("introduction", searchText)
            );
        }
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(reviewStatus), "reviewStatus", reviewStatus);
        pictureQueryWrapper.like(StrUtil.isNotBlank(reviewMessage), "reviewMessage", reviewMessage);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(reviewerId), "reviewerId", reviewerId);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        pictureQueryWrapper.like(StrUtil.isNotBlank(name), "name", name);
        pictureQueryWrapper.like(StrUtil.isNotBlank(introduction), "introduction", introduction);
        pictureQueryWrapper.like(StrUtil.isNotBlank(picFormat), "picFormat", picFormat);
        pictureQueryWrapper.eq(StrUtil.isNotBlank(category), "category", category);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(picWidth), "picWidth", picWidth);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(picHeight), "picHeight", picHeight);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(picSize), "picSize", picSize);
        pictureQueryWrapper.eq(ObjUtil.isNotEmpty(picScale), "picScale", picScale);

        if (CollUtil.isNotEmpty(tags)) {
            for (String tag : tags) {
                pictureQueryWrapper.like("tags", "\"" + tag + "\"");
            }
        }

        pictureQueryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return pictureQueryWrapper;
    }

    /**
     * 获取单个图片
     *
     * @param picture
     * @return
     */
    @Override
    public PictureVO getPictureVO(Picture picture, HttpServletRequest request) {
        PictureVO pictureVO = PictureVO.objToVo(picture);
        Long userId = picture.getUserId();
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            UserVO userVO = userService.getUserVO(user);
            pictureVO.setUser(userVO);
        }
        return pictureVO;
    }

    /**
     * 将Picture实体分页转换为PictureVO分页的方法
     * 主要负责数据格式转换和关联用户信息的填充
     *
     * @param picturePage 数据库查询得到的Picture实体分页对象
     * @param request     HTTP请求对象(预留扩展用)
     * @return 转换后的PictureVO分页对象，包含完整的视图层所需数据
     */
    @Override
    public Page<PictureVO> getPictureVOPage(Page<Picture> picturePage, HttpServletRequest request) {
        // 1. 获取分页中的实体列表
        List<Picture> pictureList = picturePage.getRecords();

        // 2. 初始化VO分页对象，保持与原分页相同的分页参数(当前页、每页大小、总条数)
        Page<PictureVO> pictureVOPage = new Page<>(
                picturePage.getCurrent(),  // 当前页码
                picturePage.getSize(),     // 每页记录数
                picturePage.getTotal()     // 总记录数
        );

        // 3. 如果实体列表为空，直接返回空的VO分页对象
        if (CollUtil.isEmpty(pictureList)) {
            return pictureVOPage;
        }

        // 4. 将Picture实体列表转换为PictureVO列表
        // 通过stream流和方法引用实现批量转换
        List<PictureVO> pictureVOList = pictureList.stream()
                .map(PictureVO::objToVo)  // 调用PictureVO的静态转换方法
                .collect(Collectors.toList());

        // 5. 收集所有图片的用户ID，用于批量查询用户信息(避免N+1查询问题)
        Set<Long> userIdSet = pictureList.stream()
                .map(Picture::getUserId)  // 提取每个图片的用户ID
                .collect(Collectors.toSet());  // 去重处理

        // 6. 批量查询用户信息，并按用户ID分组(键为用户ID，值为对应的用户列表)
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));  // 按用户ID分组

        // 7. 为每个PictureVO填充关联的用户信息
        pictureVOList.forEach(pictureVO -> {
            // 获取当前图片的用户ID
            Long userId = pictureVO.getUserId();

            // 从用户映射中获取对应的用户对象(每个ID理论上只有一个用户)
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }

            // 将User转换为UserVO并设置到PictureVO中
            pictureVO.setUser(userService.getUserVO(user));
        });

        // 8. 将转换后的VO列表设置到VO分页对象中
        pictureVOPage.setRecords(pictureVOList);

        // 返回完整的VO分页对象
        return pictureVOPage;
    }

    /**
     * 编辑图片判断
     *
     * @param picture
     */
    @Override
    public void validPicture(Picture picture) {
        ThrowUtils.throwIf(picture == null, ErrorCode.PARAMS_ERROR);

        Long id = picture.getId();
        String url = picture.getUrl();
        String introduction = picture.getIntroduction();

        ThrowUtils.throwIf(ObjUtil.isNull(id), ErrorCode.PARAMS_ERROR, "id 不能为空");
        if (StrUtil.isNotBlank(url)) {
            ThrowUtils.throwIf(url.length() > 1024, ErrorCode.PARAMS_ERROR, "url 过长");
        }
        if (StrUtil.isNotBlank(introduction)) {
            ThrowUtils.throwIf(introduction.length() > 800, ErrorCode.PARAMS_ERROR, "简介过长");
        }
    }

    /**
     * 图片审核
     *
     * @param pictureReviewDto
     * @param loginUser
     */
    @Override
    public void doPictureReview(PictureReviewDto pictureReviewDto, User loginUser) {
        Long id = pictureReviewDto.getId();
        Integer reviewStatus = pictureReviewDto.getReviewStatus();
        PictureReviewStatusEnum enumByValue = PictureReviewStatusEnum.getEnumByValue(reviewStatus);
        //判断请求参数
        ThrowUtils.throwIf(PictureReviewStatusEnum.REVIEWING.equals(enumByValue) ||
                id == null || reviewStatus == null, ErrorCode.PARAMS_ERROR);

        Picture pic = this.getById(id);
        ThrowUtils.throwIf(pic == null, ErrorCode.NOT_FOUND_ERROR);
        //判断是否是当前状态
        ThrowUtils.throwIf(pic.getReviewStatus().equals(reviewStatus), new BusinessException(ErrorCode.SYSTEM_ERROR, "请不要重复审核"));

        //更新状态
        Picture picture = new Picture();
        BeanUtils.copyProperties(pictureReviewDto, picture);
        picture.setReviewerId(loginUser.getId());
        picture.setReviewTime(new Date());
        boolean b = this.updateById(picture);
        ThrowUtils.throwIf(!b, new BusinessException(ErrorCode.OPERATION_ERROR, "修改失败"));
    }

    /**
     * 是管理员直接通过，不是管理员这进入审核
     *
     * @param picture
     * @param loginUser
     */
    @Override
    public void fillReviewParams(Picture picture, User loginUser) {
        if (userService.isAdmin(loginUser)) {
            //是管理员
            picture.setReviewStatus(PictureReviewStatusEnum.PASS.getValue());
            picture.setReviewMessage("管理员自动过审");
            picture.setReviewerId(loginUser.getId());
            picture.setReviewTime(new Date());
        } else {
            picture.setReviewStatus(PictureReviewStatusEnum.REVIEWING.getValue());
        }
    }

//    @Override
//    public PictureVO uploadPictureurl(PictureUploadDto pictureUploadDto, User loginUser) {
//        ThrowUtils.throwIf(pictureUploadDto == null, ErrorCode.PARAMS_ERROR);
//        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);
//        UploadPictureResult uploadPictureResult = fileManager.uploadPictureByUrl(pictureUploadDto.getFileUrl(), FileConstant.File + loginUser.getId());
//
//        return null;
//    }


}




